using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using WPCoco.DataStrucure;

namespace WPCoco.Graphics
{
    public static class RenderTargetCache
    {
        static RenderTargetCache()
        {
            ReleaseTarget(RetainTargetWidthSize(new Size(Screen.Width, Screen.Height)));
        }

        const int Max_RenderTargets = 10;

        static List<RenderTarget2D> unused = new List<RenderTarget2D>();
        static Set<RenderTarget2D> used = new Set<RenderTarget2D>();

        static void PruneCache() 
        {
            while (unused.Count >= Max_RenderTargets)
                unused.RemoveAt(unused.Count - 1);
        }

        static void AddRenderTarget(RenderTarget2D target) 
        {
            PruneCache();
            unused.Add(target);
        }

        static void UseRenderTarget(int index) 
        {
            RenderTarget2D target = unused[index];
            unused.RemoveAt(index);
            used.Add(target);
        }

        static void UseRenderTarget(RenderTarget2D target)
        {
            int index = unused.IndexOf(target);
            UseRenderTarget(index);
        }

        static void UnuseRenderTarget(RenderTarget2D target) 
        {
            used.Remove(target);
            PruneCache();
            unused.Add(target);            
        }



        static RenderTarget2D FindTargetWithSize(Size s) 
        {
            RenderTarget2D target = null;
            for (int i = 0; i < unused.Count; i++)
            {
                target = unused[i];
                if (target.Width >= s.Width && target.Height >= s.Height)
                    return target;
            }
            return target;
        }

        static int FindTargetIndexWithSize(Size s)
        {
            RenderTarget2D target = null;
            for (int i = 0; i < unused.Count; i++)
            {
                target = unused[i];
                if (target.Width >= s.Width && target.Height >= s.Height)
                    return i;
            }
            return -1;
        }

        public static RenderTarget2D RetainTargetWidthSize(Size size)
        {
            if (size.Width > 1024 || size.Height > 1024)
                size = new Size(Math.Min(size.Width, 1024), Math.Min(size.Height, 1024));

            RenderTarget2D target;
            int index = FindTargetIndexWithSize(size);
            if (index == -1)
            {
                target = new RenderTarget2D(Screen.CurrentGraphicsDevice,
                                            size.Width,
                                            size.Height,
                                            false,
                                            SurfaceFormat.Color,
                                            Screen.CurrentGraphicsDevice.PresentationParameters.DepthStencilFormat,
                                            Screen.CurrentGraphicsDevice.PresentationParameters.MultiSampleCount,
                                            RenderTargetUsage.PreserveContents);
                AddRenderTarget(target);
                UseRenderTarget(unused.Count - 1);
            }
            else 
            {
                target = unused[index];
                UseRenderTarget(index);
            }
            return target;
        }

        public static void ReleaseTarget(RenderTarget2D target) 
        {
            UnuseRenderTarget(target);
        }
    }
}
